]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
inputMethod: Compare ibus context before processing key event result
authorCarlos Garnacho <carlosg@gnome.org>
Thu, 7 Nov 2019 18:06:15 +0000 (19:06 +0100)
committerFlorian Müllner <florian.muellner@gmail.com>
Fri, 8 Nov 2019 12:23:15 +0000 (12:23 +0000)
In the xwayland-on-demand scenario, it may happen that Xwayland is
shutdown (causing a restart of ibus-daemon to drop ibus-x11) while
we are typing.

If we have a bit of bad luck, this will cause the IBusInputContext
to be disposed (due to its bus "closing") at a time when we have
an ibus_input_context_process_key_event_async() request on the fly.

As the object is disposed in between this would tickle JS (rightfully
complaining that it's been disposed under its feet) and make us pass
an actually NULL IBusInputContext to the corresponding _finish()
function (despite the IBusInputContext being still held alive by some
other refs). This will assert and abort in
ibus_input_context_process_key_event_async_finish() then.

To handle this, listen for IBusInputContext::destroy, and reset our
internal state, this way we can compare on the JS side that the
IBusInputContext is indeed an up-to-date one.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/813

js/misc/inputMethod.js

index 42bf7f63218b73e37eeca780f0ac490beabe5404..545cea63af562c3a313ea02d0c78ab345afa2207 100644 (file)
@@ -69,6 +69,7 @@ class InputMethod extends Clutter.InputMethod {
         this._context.connect('show-preedit-text', this._onShowPreeditText.bind(this));
         this._context.connect('hide-preedit-text', this._onHidePreeditText.bind(this));
         this._context.connect('forward-key-event', this._onForwardKeyEvent.bind(this));
+        this._context.connect('destroy', this._clear.bind(this));
 
         this._updateCapabilities();
     }
@@ -264,6 +265,9 @@ class InputMethod extends Clutter.InputMethod {
             event.get_key_code() - 8, // Convert XKB keycodes to evcodes
             state, -1, this._cancellable,
             (context, res) => {
+                if (context != this._context)
+                    return;
+
                 try {
                     let retval = context.process_key_event_async_finish(res);
                     this.notify_key_event(event, retval);